package cn.harry.cabinet.arcface.util;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.lang.ref.WeakReference;

/**
 * 内存监控工具类
 * 用于监控应用内存使用情况，防止内存泄漏和OOM
 */
public class MemoryMonitor {
    private static final String TAG = "MemoryMonitor";
    private static final long MONITOR_INTERVAL = 5000; // 5秒检查一次
    private static final long MEMORY_WARNING_THRESHOLD = 150 * 1024 * 1024; // 150MB警告阈值
    private static final long MEMORY_CRITICAL_THRESHOLD = 100 * 1024 * 1024; // 100MB严重警告阈值
    
    // 静态实例，确保全局只有一个监控器在运行
    private static volatile MemoryMonitor instance;
    private static final Object lock = new Object();
    
    private Handler monitorHandler;
    private Runnable monitorRunnable;
    private WeakReference<MemoryCallback> callbackRef;
    private boolean isMonitoring = false;
    
    public interface MemoryCallback {
        void onMemoryWarning(long usedMemory, long maxMemory, long availableMemory);
        void onMemoryCritical(long usedMemory, long maxMemory, long availableMemory);
    }
    
    private MemoryMonitor() {
        monitorHandler = new Handler(Looper.getMainLooper());
        // 使用静态内部类避免持有外部类引用
        monitorRunnable = new MonitorRunnable();
    }
    
    /**
     * 获取单例实例
     */
    public static MemoryMonitor getInstance() {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new MemoryMonitor();
                }
            }
        }
        return instance;
    }
    
    /**
     * 开始监控内存
     */
    public void startMonitoring(MemoryCallback callback) {
        synchronized (lock) {
            if (isMonitoring) {
                Log.w(TAG, "内存监控已在运行中");
                return;
            }
            
            this.callbackRef = new WeakReference<>(callback);
            isMonitoring = true;
            
            Log.i(TAG, "开始内存监控，检查间隔: " + MONITOR_INTERVAL + "ms");
            monitorHandler.post(monitorRunnable);
        }
    }
    
    /**
     * 停止监控内存
     */
    public void stopMonitoring() {
        synchronized (lock) {
            if (!isMonitoring) {
                return;
            }
            
            isMonitoring = false;
            monitorHandler.removeCallbacks(monitorRunnable);
            
            if (callbackRef != null) {
                callbackRef.clear();
                callbackRef = null;
            }
            
            Log.i(TAG, "内存监控已停止");
        }
    }
    
    /**
     * 检查当前内存状态
     */
    private void checkMemory() {
        try {
            Runtime runtime = Runtime.getRuntime();
            long maxMemory = runtime.maxMemory();
            long totalMemory = runtime.totalMemory();
            long freeMemory = runtime.freeMemory();
            long usedMemory = totalMemory - freeMemory;
            long availableMemory = maxMemory - usedMemory;
            
            Log.d(TAG, String.format("内存状态 - 最大: %dMB, 已用: %dMB, 可用: %dMB", 
                maxMemory / 1024 / 1024, 
                usedMemory / 1024 / 1024, 
                availableMemory / 1024 / 1024));
            
            MemoryCallback callback = callbackRef != null ? callbackRef.get() : null;
            if (callback != null) {
                if (availableMemory < MEMORY_CRITICAL_THRESHOLD) {
                    Log.w(TAG, "内存严重警告: 可用内存不足100MB");
                    callback.onMemoryCritical(usedMemory, maxMemory, availableMemory);
                } else if (availableMemory < MEMORY_WARNING_THRESHOLD) {
                    Log.w(TAG, "内存警告: 可用内存不足150MB");
                    callback.onMemoryWarning(usedMemory, maxMemory, availableMemory);
                }
            } else {
                // 回调已被回收，停止监控
                Log.w(TAG, "内存监控回调已被回收，停止监控");
                stopMonitoring();
            }
        } catch (Exception e) {
            Log.e(TAG, "检查内存状态时出错", e);
        }
    }
    
    /**
     * 强制垃圾回收
     */
    public void forceGarbageCollection() {
        try {
            Log.i(TAG, "强制垃圾回收");
            System.gc();
            
            // 等待垃圾回收完成
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            // 再次检查内存状态
            checkMemory();
        } catch (Exception e) {
            Log.e(TAG, "强制垃圾回收时出错", e);
        }
    }
    
    /**
     * 获取当前内存使用情况
     */
    public MemoryInfo getCurrentMemoryInfo() {
        try {
            Runtime runtime = Runtime.getRuntime();
            long maxMemory = runtime.maxMemory();
            long totalMemory = runtime.totalMemory();
            long freeMemory = runtime.freeMemory();
            long usedMemory = totalMemory - freeMemory;
            long availableMemory = maxMemory - usedMemory;
            
            return new MemoryInfo(maxMemory, totalMemory, freeMemory, usedMemory, availableMemory);
        } catch (Exception e) {
            Log.e(TAG, "获取内存信息时出错", e);
            return new MemoryInfo(0, 0, 0, 0, 0);
        }
    }
    
    /**
     * 检查监控状态
     */
    public boolean isMonitoring() {
        synchronized (lock) {
            return isMonitoring;
        }
    }
    
    /**
     * 清理资源
     */
    public void destroy() {
        synchronized (lock) {
            stopMonitoring();
            if (monitorHandler != null) {
                monitorHandler.removeCallbacksAndMessages(null);
                monitorHandler = null;
            }
            monitorRunnable = null;
            instance = null;
            Log.i(TAG, "MemoryMonitor已销毁");
        }
    }
    
    /**
     * 静态内部类，避免持有外部类引用
     */
    private static class MonitorRunnable implements Runnable {
        @Override
        public void run() {
            if (instance != null && instance.isMonitoring) {
                instance.checkMemory();
                if (instance.monitorHandler != null) {
                    instance.monitorHandler.postDelayed(this, MONITOR_INTERVAL);
                }
            }
        }
    }
    
    /**
     * 内存信息类
     */
    public static class MemoryInfo {
        public final long maxMemory;
        public final long totalMemory;
        public final long freeMemory;
        public final long usedMemory;
        public final long availableMemory;
        
        public MemoryInfo(long maxMemory, long totalMemory, long freeMemory, long usedMemory, long availableMemory) {
            this.maxMemory = maxMemory;
            this.totalMemory = totalMemory;
            this.freeMemory = freeMemory;
            this.usedMemory = usedMemory;
            this.availableMemory = availableMemory;
        }
        
        public String getFormattedInfo() {
            return String.format("最大: %dMB, 已用: %dMB, 可用: %dMB", 
                maxMemory / 1024 / 1024, 
                usedMemory / 1024 / 1024, 
                availableMemory / 1024 / 1024);
        }
    }
} 